/*
* INSANE - Interactive Structural Analysis Environment
*
* Copyright (C) 2003-2005
* Universidade Federal de Minas Gerais
* Escola de Engenharia
* Departamento de Engenharia de Estruturas
* 
* Author's email :    insane@dees.ufmg.br
* Author's website :  http://www.dees.ufmg.br/insane
* 
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or any later version.
* 
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
* GNU General Public License for more details.
* 
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
*/
package br.ufmg.dees.insane.reports;

//Java
import java.io.IOException;
import java.text.DecimalFormat;
import java.text.DecimalFormatSymbols;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.ListIterator;

import org.xml.sax.InputSource;
import org.xml.sax.SAXException;

import br.ufmg.dees.insane.crossSection.CrossSection;
import br.ufmg.dees.insane.materialMedia.material.LinearElasticIsotropic;
import br.ufmg.dees.insane.materialMedia.material.MSpring;
import br.ufmg.dees.insane.materialMedia.material.Material;
import br.ufmg.dees.insane.model.Model;
import br.ufmg.dees.insane.model.disc.element.FrameElement;
import br.ufmg.dees.insane.model.disc.element.force.ElementForce;
import br.ufmg.dees.insane.model.disc.fem.FemModel;
import br.ufmg.dees.insane.model.disc.node.Node;
import br.ufmg.dees.insane.model.disc.pointforce.PointForce;

/**
 * XMLReader implementation for the Model class. This class is used to
 * generate SAX events from the Model class.
 */
public class ModelXMLReader extends AbstractObjectReader {
	
	DecimalFormat fmt = new DecimalFormat();
	DecimalFormatSymbols fsym = new DecimalFormatSymbols();
	String gAnl = " ";
	String drawingFile;
	
//********************************************************************************
	
	public ModelXMLReader() {
		//Setting formator
		fsym.setDecimalSeparator('.');
		fmt.setDecimalFormatSymbols(fsym);
	}
	
//********************************************************************************
	
	public ModelXMLReader(String drawingFile) {
		//Setting formator
		fsym.setDecimalSeparator('.');
		fmt.setDecimalFormatSymbols(fsym);
		this.drawingFile = drawingFile;
	}
	
//********************************************************************************
	
    /**
     * @see org.xml.sax.XMLReader#parse(InputSource)
     */
    public void parse(InputSource input) throws IOException, SAXException {
        if (input instanceof ModelInputSource) {
            parse(((ModelInputSource)input).getModel());
        } else {
            throw new SAXException("Unsupported InputSource specified. Must be a ModelInputSource");
        }
    }
	
//********************************************************************************
	
    /**
     * Starts parsing the Model object.
     * @param model The object to parse
     * @throws SAXException In case of a problem during SAX event generation
     */
    public void parse(Model model) throws SAXException {
        if (model == null) {
            throw new NullPointerException("Parameter model must not be null");
        }
        if (handler == null) {
            throw new IllegalStateException("ContentHandler not set");
        }
        
        //Start the document
        handler.startDocument();
        
        //Generate SAX events for the Model
        generateFor(model);
        
        //End the document
        handler.endDocument();
    }
	
//********************************************************************************
	
    /**
     * Generates SAX events for a Model object.
     * @param model Model object to use
     * @throws SAXException In case of a problem during SAX event generation
     */
    protected void generateFor(Model model) throws SAXException {
        if (model == null) {
            throw new NullPointerException("Parameter model must not be null");
        }
        if (handler == null) {
            throw new IllegalStateException("ContentHandler not set");
        }
        
		//main element of XML
		handler.startElement("root");
        
		//drawing file
		handler.element("drawing", drawingFile);
		
		//file attributes
		handler.element("filename", String.valueOf(model.getState().getName()));
		
		Date currentDate;
		SimpleDateFormat dateStile = new SimpleDateFormat("dd/MM/yyyy"); 
		SimpleDateFormat timeStile = new SimpleDateFormat("HH:mm:ss"); 
		currentDate = new Date();
		handler.element("date", dateStile.format(currentDate));
		handler.element("time", timeStile.format(currentDate));
		
		FemModel fmodel = model.getDiscreteModel();
		generateFor(fmodel);
		
        handler.endElement("root");
    }
	
//********************************************************************************
	
    /**
     * Generates SAX events for a FemModel object.
     * @param fmodel FemModel object to use
     * @throws SAXException In case of a problem during SAX event generation
     */
    protected void generateFor(FemModel fmodel) throws SAXException {
        if (fmodel == null) {
            throw new NullPointerException("Parameter fmodel must not be null");
        }
        if (handler == null) {
            throw new IllegalStateException("ContentHandler not set");
        }
        
        handler.startElement("fmodel");
		
		//Model attributes
        handler.element("numEquations", String.valueOf(fmodel.getNumberOfEquations()));
		handler.element("numRestraints", String.valueOf(fmodel.getNumberOfRestraints()));
		handler.element("numNodes", String.valueOf(fmodel.getNumberOfNodes() - fmodel.getNumberOfElasticElements()));
		handler.element("numElements", String.valueOf(fmodel.getNumberOfNonElasticElements()));
		handler.element("numMaterials", String.valueOf(fmodel.getNumberOfIsotropicMaterials()));
		handler.element("numSections", String.valueOf(fmodel.getNumberOfSections()));
		handler.element("globalAnalysis", String.valueOf(fmodel.getGlobalAnalysisModel().getType()));
		handler.element("hypostatic", String.valueOf(fmodel.isHypostatic()));
		gAnl = String.valueOf(fmodel.getGlobalAnalysisModel().getType());
		
		//Nodes
		ListIterator i = fmodel.getNodesList().listIterator();
        while (i.hasNext()) {
            Node node = (Node)i.next();
            generateFor(node);
        }
		
		//Isotropic Materials
		i = fmodel.getMaterialsList().listIterator();
        while (i.hasNext()) {
            Material mat = (Material)i.next();
			if (mat instanceof LinearElasticIsotropic)
				generateFor((LinearElasticIsotropic)mat);
        }
		
		//Cross Sections
        i = fmodel.getSectionsList().listIterator();
        while (i.hasNext()) {
            CrossSection cs = (CrossSection)i.next();
            generateFor(cs);
        }
		
		//Elements without MSpring Material
		i = fmodel.getElementsList().listIterator();
        while (i.hasNext()) {
            FrameElement elm = (FrameElement)i.next();
            if (!(elm.getMaterial() instanceof MSpring))
				generateFor(elm);
        }
		
		handler.endElement("fmodel");
    }
	
//********************************************************************************
	
	/**
     * Generates SAX events for a Node object.
     * @param node Node object to use
     * @throws SAXException In case of a problem during SAX event generation
     */
    protected void generateFor(Node node) throws SAXException {
        if (node == null) {
            throw new NullPointerException("Parameter node must not be null");
        }
        if (handler == null) {
            throw new IllegalStateException("ContentHandler not set");
        }
        
		//Node attributes
		fmt.applyPattern("####0.000");
        handler.startElement("node");
        handler.element("label", node.getLabel());
		handler.element("x", fmt.format(node.getCoord().x));
		handler.element("y", fmt.format(node.getCoord().y));
		handler.element("z", fmt.format(node.getCoord().z));
		handler.element("angle", fmt.format(node.getAngle()));
		
		//Restraints
		boolean hasRestraint = false;
		if (gAnl.equals("PlaneTruss") && (node.getRestraint(0) || node.getRestraint(1)))
			hasRestraint = true;
		if (gAnl.equals("Beam") && (node.getRestraint(1) || node.getRestraint(5)))
			hasRestraint = true;
		if (gAnl.equals("Grid") && (node.getRestraint(1) || node.getRestraint(3) || node.getRestraint(5)))
			hasRestraint = true;
		if (gAnl.equals("PlaneFrame") && (node.getRestraint(0) || node.getRestraint(1) || node.getRestraint(5)))
			hasRestraint = true;
		if (gAnl.equals("SpaceTruss") && (node.getRestraint(0) || node.getRestraint(1) || node.getRestraint(2)))
			hasRestraint = true;
		if (gAnl.equals("SpaceFrame") && (node.getRestraint(0) || node.getRestraint(1) || node.getRestraint(2) || node.getRestraint(3) || node.getRestraint(4) || node.getRestraint(5)))
			hasRestraint = true;
		
		if (hasRestraint) {
			handler.startElement("restraint");
			handler.element("dx", String.valueOf(node.getRestraint(0)));
			handler.element("dy", String.valueOf(node.getRestraint(1)));
			handler.element("dz", String.valueOf(node.getRestraint(2)));
			handler.element("rx", String.valueOf(node.getRestraint(3)));
			handler.element("ry", String.valueOf(node.getRestraint(4)));
			handler.element("rz", String.valueOf(node.getRestraint(5)));
			handler.endElement("restraint");
		}
		
		//Force
		boolean hasForce = false;
		if (gAnl.equals("PlaneTruss") && (node.getForce(0)!=0 || node.getForce(1)!=0))
			hasForce = true;
		if (gAnl.equals("Beam") && (node.getForce(1)!=0 || node.getForce(5)!=0))
			hasForce = true;
		if (gAnl.equals("Grid") && (node.getForce(1)!=0 || node.getForce(3)!=0 || node.getForce(5)!=0))
			hasForce = true;
		if (gAnl.equals("PlaneFrame") && (node.getForce(0)!=0 || node.getForce(1)!=0 || node.getForce(5)!=0))
			hasForce = true;
		if (gAnl.equals("SpaceTruss") && (node.getForce(0)!=0 || node.getForce(1)!=0 || node.getForce(2)!=0))
			hasForce = true;
		if (gAnl.equals("SpaceFrame") && (node.getForce(0)!=0 || node.getForce(1)!=0 || node.getForce(2)!=0 || node.getForce(3)!=0 || node.getForce(4)!=0 || node.getForce(5)!=0))
			hasForce = true;
		
		if (hasForce) {
			handler.startElement("force");
			handler.element("fx", String.valueOf(node.getForce(0)));
			handler.element("fy", String.valueOf(node.getForce(1)));
			handler.element("fz", String.valueOf(node.getForce(2)));
			handler.element("mx", String.valueOf(node.getForce(3)));
			handler.element("my", String.valueOf(node.getForce(4)));
			handler.element("mz", String.valueOf(node.getForce(5)));
			handler.endElement("force");
		}
		
		//mySpring
		boolean hasSpring = false;
		if (gAnl.equals("PlaneTruss") && (node.getSpring(0)!=0 || node.getSpring(1)!=0))
			hasSpring = true;
		if (gAnl.equals("Beam") && (node.getSpring(1)!=0 || node.getSpring(5)!=0))
			hasSpring = true;
		if (gAnl.equals("Grid") && (node.getSpring(1)!=0 || node.getSpring(3)!=0 || node.getSpring(5)!=0))
			hasSpring = true;
		if (gAnl.equals("PlaneFrame") && (node.getSpring(0)!=0 || node.getSpring(1)!=0 || node.getSpring(5)!=0))
			hasSpring = true;
		if (gAnl.equals("SpaceTruss") && (node.getSpring(0)!=0 || node.getSpring(1)!=0 || node.getSpring(2)!=0))
			hasSpring = true;
		if (gAnl.equals("SpaceFrame") && (node.getSpring(0)!=0 || node.getSpring(1)!=0 || node.getSpring(2)!=0 || node.getSpring(3)!=0 || node.getSpring(4)!=0 || node.getSpring(5)!=0))
			hasSpring = true;
		
		if (hasSpring) {
			fmt.applyPattern("0.000E00");
			handler.startElement("spring");
			handler.element("dx", fmt.format(node.getSpring(0)));
			handler.element("dy", fmt.format(node.getSpring(1)));
			handler.element("dz", fmt.format(node.getSpring(2)));
			handler.element("rx", fmt.format(node.getSpring(3)));
			handler.element("ry", fmt.format(node.getSpring(4)));
			handler.element("rz", fmt.format(node.getSpring(5)));
			handler.endElement("spring");
		}
		
        //Prescribed Displacements
		boolean hasPreDisplacement = false;
		if (gAnl.equals("PlaneTruss") && (node.getPreDisplacement(0)!=0 || node.getPreDisplacement(1)!=0))
			hasPreDisplacement = true;
		if (gAnl.equals("Beam") && (node.getPreDisplacement(1)!=0 || node.getPreDisplacement(5)!=0))
			hasPreDisplacement = true;
		if (gAnl.equals("Grid") && (node.getPreDisplacement(1)!=0 || node.getPreDisplacement(3)!=0 || node.getPreDisplacement(5)!=0))
			hasPreDisplacement = true;
		if (gAnl.equals("PlaneFrame") && (node.getPreDisplacement(0)!=0 || node.getPreDisplacement(1)!=0 || node.getPreDisplacement(5)!=0))
			hasPreDisplacement = true;
		if (gAnl.equals("SpaceTruss") && (node.getPreDisplacement(0)!=0 || node.getPreDisplacement(1)!=0 || node.getPreDisplacement(2)!=0))
			hasPreDisplacement = true;
		if (gAnl.equals("SpaceFrame") && (node.getPreDisplacement(0)!=0 || node.getPreDisplacement(1)!=0 || node.getPreDisplacement(2)!=0 || node.getPreDisplacement(3)!=0 || node.getPreDisplacement(4)!=0 || node.getPreDisplacement(5)!=0))
			hasPreDisplacement = true;
		
		if (hasPreDisplacement) {
			fmt.applyPattern("0.000E00");
			handler.startElement("preDisplacement");
			handler.element("dx", fmt.format(node.getPreDisplacement(0)));
			handler.element("dy", fmt.format(node.getPreDisplacement(1)));
			handler.element("dz", fmt.format(node.getPreDisplacement(2)));
			handler.element("rx", fmt.format(node.getPreDisplacement(3)));
			handler.element("ry", fmt.format(node.getPreDisplacement(4)));
			handler.element("rz", fmt.format(node.getPreDisplacement(5)));
			handler.endElement("preDisplacement");
		}
		
		//Displacements
		fmt.applyPattern("0.000E00");
		handler.startElement("Displacement");
		handler.element("dx", fmt.format(node.getDisplacement(0)));
		handler.element("dy", fmt.format(node.getDisplacement(1)));
		handler.element("dz", fmt.format(node.getDisplacement(2)));
		handler.element("rx", fmt.format(node.getDisplacement(3)));
		handler.element("ry", fmt.format(node.getDisplacement(4)));
		handler.element("rz", fmt.format(node.getDisplacement(5)));
		handler.endElement("Displacement");
		
		//Reactions
		boolean hasReactions = false;
		if (gAnl.equals("PlaneTruss") && (node.getRestraint(0) || node.getRestraint(1)))
			hasReactions = true;
		if (gAnl.equals("Beam") && (node.getRestraint(1) || node.getRestraint(5)))
			hasReactions = true;
		if (gAnl.equals("Grid") && (node.getRestraint(1) || node.getRestraint(3) || node.getRestraint(5)))
			hasReactions = true;
		if (gAnl.equals("PlaneFrame") && (node.getRestraint(0) || node.getRestraint(1) || node.getRestraint(5)))
			hasReactions = true;
		if (gAnl.equals("SpaceTruss") && (node.getRestraint(0) || node.getRestraint(1) || node.getRestraint(2)))
			hasReactions = true;
		if (gAnl.equals("SpaceFrame") && (node.getRestraint(0) || node.getRestraint(1) || node.getRestraint(2) || node.getRestraint(3) || node.getRestraint(4) || node.getRestraint(5)))
			hasReactions = true;
		
		if (hasReactions) {
			fmt.applyPattern("####0.000");
			handler.startElement("reactions");
			handler.element("dx", fmt.format(node.getReaction(0)));
			handler.element("dy", fmt.format(node.getReaction(1)));
			handler.element("dz", fmt.format(node.getReaction(2)));
			handler.element("rx", fmt.format(node.getReaction(3)));
			handler.element("ry", fmt.format(node.getReaction(4)));
			handler.element("rz", fmt.format(node.getReaction(5)));
			handler.endElement("reactions");
		}
		
		//Force on Springs
		boolean hasElaReactions = false;
		if (gAnl.equals("PlaneTruss") && (node.getSpring(0)!=0 || node.getSpring(1)!=0))
			hasElaReactions = true;
		if (gAnl.equals("Beam") && (node.getSpring(1)!=0 || node.getSpring(5)!=0))
			hasElaReactions = true;
		if (gAnl.equals("Grid") && (node.getSpring(1)!=0 || node.getSpring(3)!=0 || node.getSpring(5)!=0))
			hasElaReactions = true;
		if (gAnl.equals("PlaneFrame") && (node.getSpring(0)!=0 || node.getSpring(1)!=0 || node.getSpring(5)!=0))
			hasElaReactions = true;
		if (gAnl.equals("SpaceTruss") && (node.getSpring(0)!=0 || node.getSpring(1)!=0 || node.getSpring(2)!=0))
			hasElaReactions = true;
		if (gAnl.equals("SpaceFrame") && (node.getSpring(0)!=0 || node.getSpring(1)!=0 || node.getSpring(2)!=0 || node.getSpring(3)!=0 || node.getSpring(4)!=0 || node.getSpring(5)!=0))
			hasElaReactions = true;
		
		if (hasElaReactions) {
			fmt.applyPattern("####0.000");
			handler.startElement("elaReactions");
			handler.element("dx", fmt.format(-node.getDisplacement(0)*node.getSpring(0)));
			handler.element("dy", fmt.format(-node.getDisplacement(1)*node.getSpring(1)));
			handler.element("dz", fmt.format(-node.getDisplacement(2)*node.getSpring(2)));;
			handler.element("rx", fmt.format(-node.getDisplacement(3)*node.getSpring(3)));
			handler.element("ry", fmt.format(-node.getDisplacement(4)*node.getSpring(4)));
			handler.element("rz", fmt.format(-node.getDisplacement(5)*node.getSpring(5)));
			handler.endElement("elaReactions");
		}
		
		handler.endElement("node");
    }
	
//********************************************************************************
	
	/**
     * Generates SAX events for a Isotropic material object.
     * @param mat Isotropic Material object to use
     * @throws SAXException In case of a problem during SAX event generation
     */
    protected void generateFor(LinearElasticIsotropic mat) throws SAXException {
        if (mat == null) {
            throw new NullPointerException("Parameter mat must not be null");
        }
        if (handler == null) {
            throw new IllegalStateException("ContentHandler not set");
        }
		
		//Isotropic Material attributes
        handler.startElement("material");
        handler.element("label", mat.getLabel());
		fmt.applyPattern("0.000E00");
		if (mat.getMaterialValues(mat.ELASTICITY).doubleValue()!=0)
			handler.element("elasticity", fmt.format(mat.getMaterialValues(mat.ELASTICITY).doubleValue()));
		if (mat.getMaterialValues(mat.SHEAR_MODULUS).doubleValue()!=0)
			handler.element("g", fmt.format(mat.getMaterialValues(mat.SHEAR_MODULUS).doubleValue()));
		if (mat.getMaterialValues(mat.THERMAL_COEFF).doubleValue()!=0)
			handler.element("thermalCoeff", fmt.format(mat.getMaterialValues(mat.THERMAL_COEFF).doubleValue()));
		fmt.applyPattern("####0.00");
		if (mat.getMaterialValues(mat.POISSON).doubleValue()!=0)
			handler.element("poisson", fmt.format(mat.getMaterialValues(mat.POISSON).doubleValue()));
		handler.endElement("material");
		
	}
	
//********************************************************************************
	
	/**
     * Generates SAX events for a CrossSection object.
     * @param cs CrossSection object to use
     * @throws SAXException In case of a problem during SAX event generation
     */
    protected void generateFor(CrossSection cs) throws SAXException {
        if (cs == null) {
            throw new NullPointerException("Parameter cs must not be null");
        }
        if (handler == null) {
            throw new IllegalStateException("ContentHandler not set");
        }
		
		//Cross Section attributes
		handler.startElement("section");
        handler.element("label", cs.getLabel());
		fmt.applyPattern("0.000E00");
		if (cs.getIx()!=0)
			handler.element("ix", fmt.format(cs.getIx()));
		if (cs.getIy()!=0)
			handler.element("iy", fmt.format(cs.getIy()));
		if (cs.getIz()!=0)
			handler.element("iz", fmt.format(cs.getIz()));
		fmt.applyPattern("####0.000");
		if (cs.getArea()!=0)
			handler.element("area", fmt.format(cs.getArea()));
		if (cs.getHeight()!=0)
			handler.element("height", fmt.format(cs.getHeight()));
		handler.endElement("section");
		
	}
	
//********************************************************************************
	
	/**
     * Generates SAX events for a FrameElement object.
     * @param elm FrameElement object to use
     * @throws SAXException In case of a problem during SAX event generation
     */
    protected void generateFor(FrameElement elm) throws SAXException {
        if (elm == null) {
            throw new NullPointerException("Parameter elm must not be null");
        }
        if (handler == null) {
            throw new IllegalStateException("ContentHandler not set");
        }
		
		//Element attributes
		handler.startElement("element");
        handler.element("label", elm.getLabel());
		handler.element("initialNode", elm.getInitialNode().getLabel());
		handler.element("finalNode", elm.getFinalNode().getLabel());
		if (elm.getMaterial() != null)
			handler.element("myMaterial", elm.getMaterial().getLabel());
		if (elm.getCrossSection() != null)
			handler.element("myCrossSection", elm.getCrossSection().getLabel());
		handler.element("myAnalysisModel", elm.getAnalysisModel().getType());
		
		//Concentrated Loads
		ListIterator i = elm.getElmPointForcesList().listIterator();
		
		while (i.hasNext()) {
			PointForce pf = (PointForce)i.next();
			boolean hasConcLoad = false;
			if (gAnl.equals("PlaneTruss") && (pf.getForce(0)!=0 || pf.getForce(1)!=0))
				hasConcLoad = true;
			if (gAnl.equals("Beam") && (pf.getForce(1)!=0 || pf.getForce(5)!=0))
				hasConcLoad = true;
			if (gAnl.equals("Grid") && (pf.getForce(1)!=0 || pf.getForce(3)!=0 || pf.getForce(5)!=0))
				hasConcLoad = true;
			if (gAnl.equals("PlaneFrame") && (pf.getForce(0)!=0 || pf.getForce(1)!=0 || pf.getForce(5)!=0))
				hasConcLoad = true;
			if (gAnl.equals("SpaceTruss") && (pf.getForce(0)!=0 || pf.getForce(1)!=0 || pf.getForce(2)!=0))
				hasConcLoad = true;
			if (gAnl.equals("SpaceFrame") && (pf.getForce(0)!=0 || pf.getForce(1)!=0 || pf.getForce(2)!=0 || pf.getForce(3)!=0 || pf.getForce(4)!=0 || pf.getForce(5)!=0))
				hasConcLoad = true;
			
			if (hasConcLoad) {
				fmt.applyPattern("####0.000");
				handler.startElement("concLoad");
				handler.element("a", fmt.format(pf.getCoord().x));
				handler.element("fx", fmt.format(pf.getForce(0)));
				handler.element("fy", fmt.format(pf.getForce(1)));
				handler.element("fz", fmt.format(pf.getForce(2)));
				handler.element("mx", fmt.format(pf.getForce(3)));
				handler.element("my", fmt.format(pf.getForce(4)));
				handler.element("mz", fmt.format(pf.getForce(5)));
				handler.endElement("concLoad");
			}
		}
		
		//Distributed Loads
		i = elm.getElmLineForcesList().listIterator();
		
		while (i.hasNext()) {
			ElementForce ef = (ElementForce)i.next();
			PointForce pfa = (PointForce)ef.getPointForcesList().get(0);
			PointForce pfb = (PointForce)ef.getPointForcesList().get(1);
			boolean hasDistLoad = false;
			if (gAnl.equals("PlaneTruss") && (pfa.getForce(0)!=0 || pfa.getForce(1)!=0 || pfb.getForce(0)!=0 || pfb.getForce(1)!=0))
				hasDistLoad = true;
			if (gAnl.equals("Beam") && (pfa.getForce(1)!=0 || pfb.getForce(1)!=0))
				hasDistLoad = true;
			if (gAnl.equals("Grid") && (pfa.getForce(1)!=0 || pfa.getForce(3)!=0 || pfb.getForce(1)!=0 || pfb.getForce(3)!=0))
				hasDistLoad = true;
			if (gAnl.equals("PlaneFrame") && (pfa.getForce(0)!=0 || pfa.getForce(1)!=0 || pfb.getForce(0)!=0 || pfb.getForce(1)!=0))
				hasDistLoad = true;
			if (gAnl.equals("SpaceTruss") && (pfa.getForce(0)!=0 || pfa.getForce(1)!=0 || pfa.getForce(2)!=0 || pfb.getForce(0)!=0 || pfb.getForce(1)!=0 || pfb.getForce(2)!=0))
				hasDistLoad = true;
			if (gAnl.equals("SpaceFrame") && (pfa.getForce(0)!=0 || pfa.getForce(1)!=0 || pfa.getForce(2)!=0 || pfa.getForce(3)!=0 || pfb.getForce(0)!=0 || pfb.getForce(1)!=0 || pfb.getForce(2)!=0 || pfb.getForce(3)!=0))
				hasDistLoad = true;
			
			if (hasDistLoad) {
				fmt.applyPattern("####0.000");
				handler.startElement("distLoad");
				handler.element("a", fmt.format(pfa.getCoord().x));
				handler.element("b", fmt.format(pfb.getCoord().x));
				handler.element("fxa", fmt.format(pfa.getForce(0)));
				handler.element("fya", fmt.format(pfa.getForce(1)));
				handler.element("fza", fmt.format(pfa.getForce(2)));
				handler.element("mxa", fmt.format(pfa.getForce(3)));
				handler.element("fxb", fmt.format(pfb.getForce(0)));
				handler.element("fyb", fmt.format(pfb.getForce(1)));
				handler.element("fzb", fmt.format(pfb.getForce(2)));
				handler.element("mxb", fmt.format(pfb.getForce(3)));
				handler.endElement("distLoad");
			}
		}
		
		//Temperature Changes
		boolean hasTempChanges = false;
		if (gAnl.equals("PlaneTruss") && (elm.getDeltaTemp(1)!=0))
			hasTempChanges = true;
		if (gAnl.equals("Beam") && (elm.getDeltaTemp(0)!=0 || elm.getDeltaTemp(2)!=0))
			hasTempChanges = true;
		if (gAnl.equals("Grid") && (elm.getDeltaTemp(0)!=0 || elm.getDeltaTemp(2)!=0))
			hasTempChanges = true;
		if (gAnl.equals("PlaneFrame") && (elm.getDeltaTemp(0)!=0 || elm.getDeltaTemp(1)!=0 || elm.getDeltaTemp(2)!=0))
			hasTempChanges = true;
		if (gAnl.equals("SpaceTruss") && (elm.getDeltaTemp(1)!=0))
			hasTempChanges = true;
		if (gAnl.equals("SpaceFrame") && (elm.getDeltaTemp(0)!=0 || elm.getDeltaTemp(1)!=0 || elm.getDeltaTemp(2)!=0))
			hasTempChanges = true;
		
		if (hasTempChanges) {
			fmt.applyPattern("####0.000");
			handler.startElement("tempChanges");
			handler.element("ts", fmt.format(elm.getDeltaTemp(0)));
			handler.element("tn", fmt.format(elm.getDeltaTemp(1)));
			handler.element("ti", fmt.format(elm.getDeltaTemp(2)));
			handler.endElement("tempChanges");
		}
		
		//Liberations
		boolean hasLiberation = false;
		if (gAnl.equals("Beam") && (elm.getLiberation(1) || elm.getLiberation(5) || elm.getLiberation(7) || elm.getLiberation(11)))
			hasLiberation = true;
		if (gAnl.equals("Grid") && (elm.getLiberation(1) || elm.getLiberation(3) || elm.getLiberation(5) || elm.getLiberation(7) || elm.getLiberation(9) || elm.getLiberation(11)))
			hasLiberation = true;
		if (gAnl.equals("PlaneFrame") && (elm.getLiberation(0) || elm.getLiberation(1) || elm.getLiberation(5) || elm.getLiberation(6) || elm.getLiberation(7) || elm.getLiberation(11)))
			hasLiberation = true;
		if (gAnl.equals("SpaceFrame") && (elm.getLiberation(0) || elm.getLiberation(1) || elm.getLiberation(2) || elm.getLiberation(3) || elm.getLiberation(4) || elm.getLiberation(5) || elm.getLiberation(6) || elm.getLiberation(7) || elm.getLiberation(8) || elm.getLiberation(9) || elm.getLiberation(10) || elm.getLiberation(11)))
			hasLiberation = true;
		
		if (hasLiberation) {
			handler.startElement("liberation");
			handler.element("dx1", String.valueOf(elm.getLiberation(0)));
			handler.element("dy1", String.valueOf(elm.getLiberation(1)));
			handler.element("dz1", String.valueOf(elm.getLiberation(2)));
			handler.element("rx1", String.valueOf(elm.getLiberation(3)));
			handler.element("ry1", String.valueOf(elm.getLiberation(4)));
			handler.element("rz1", String.valueOf(elm.getLiberation(5)));
			handler.element("dx2", String.valueOf(elm.getLiberation(6)));
			handler.element("dy2", String.valueOf(elm.getLiberation(7)));
			handler.element("dz2", String.valueOf(elm.getLiberation(8)));
			handler.element("rx2", String.valueOf(elm.getLiberation(9)));
			handler.element("ry2", String.valueOf(elm.getLiberation(10)));
			handler.element("rz2", String.valueOf(elm.getLiberation(11)));
			handler.endElement("liberation");
		}
		
		//Pre-Strains
		boolean hasPreStrains = false;
		if (gAnl.equals("PlaneTruss") && (elm.getElmPreDisplacement(0)!=0 || elm.getElmPreDisplacement(1)!=0 || elm.getElmPreDisplacement(6)!=0 || elm.getElmPreDisplacement(7)!=0))
			hasPreStrains = true;
		if (gAnl.equals("Beam") && (elm.getElmPreDisplacement(1)!=0 || elm.getElmPreDisplacement(5)!=0 || elm.getElmPreDisplacement(7)!=0 || elm.getElmPreDisplacement(11)!=0))
			hasPreStrains = true;
		if (gAnl.equals("Grid") && (elm.getElmPreDisplacement(1)!=0 || elm.getElmPreDisplacement(3)!=0 || elm.getElmPreDisplacement(5)!=0 || elm.getElmPreDisplacement(7)!=0 || elm.getElmPreDisplacement(9)!=0 || elm.getElmPreDisplacement(11)!=0))
			hasPreStrains = true;
		if (gAnl.equals("PlaneFrame") && (elm.getElmPreDisplacement(0)!=0 || elm.getElmPreDisplacement(1)!=0 || elm.getElmPreDisplacement(5)!=0 || elm.getElmPreDisplacement(6)!=0 || elm.getElmPreDisplacement(7)!=0 || elm.getElmPreDisplacement(11)!=0))
			hasPreStrains = true;
		if (gAnl.equals("SpaceTruss") && (elm.getElmPreDisplacement(0)!=0 || elm.getElmPreDisplacement(1)!=0 || elm.getElmPreDisplacement(2)!=0 || elm.getElmPreDisplacement(6)!=0 || elm.getElmPreDisplacement(7)!=0 || elm.getElmPreDisplacement(8)!=0))
			hasPreStrains = true;
		if (gAnl.equals("SpaceFrame") && (elm.getElmPreDisplacement(0)!=0 || elm.getElmPreDisplacement(1)!=0 || elm.getElmPreDisplacement(2)!=0 || elm.getElmPreDisplacement(3)!=0 || elm.getElmPreDisplacement(4)!=0 || elm.getElmPreDisplacement(5)!=0 || elm.getElmPreDisplacement(6)!=0 || elm.getElmPreDisplacement(7)!=0 || elm.getElmPreDisplacement(8)!=0 || elm.getElmPreDisplacement(9)!=0 || elm.getElmPreDisplacement(10)!=0 || elm.getElmPreDisplacement(11)!=0))
			hasPreStrains = true;
		
		if (hasPreStrains) {
			fmt.applyPattern("0.000E00");
			handler.startElement("preStrain");
			handler.element("dx1", fmt.format(elm.getElmPreDisplacement(0)));
			handler.element("dy1", fmt.format(elm.getElmPreDisplacement(1)));
			handler.element("dz1", fmt.format(elm.getElmPreDisplacement(2)));
			handler.element("rx1", fmt.format(elm.getElmPreDisplacement(3)));
			handler.element("ry1", fmt.format(elm.getElmPreDisplacement(4)));
			handler.element("rz1", fmt.format(elm.getElmPreDisplacement(5)));
			handler.element("dx2", fmt.format(elm.getElmPreDisplacement(6)));
			handler.element("dy2", fmt.format(elm.getElmPreDisplacement(7)));
			handler.element("dz2", fmt.format(elm.getElmPreDisplacement(8)));
			handler.element("rx2", fmt.format(elm.getElmPreDisplacement(9)));
			handler.element("ry2", fmt.format(elm.getElmPreDisplacement(10)));
			handler.element("rz2", fmt.format(elm.getElmPreDisplacement(11)));
			handler.endElement("preStrain");
		}
		
		//Initial Equivalent Nodal Force
		boolean hasIniEqForce = false;
		if (gAnl.equals("PlaneTruss") && (elm.getInitialNodalForce(0)!=0 || elm.getInitialNodalForce(1)!=0 || elm.getInitialNodalForce(6)!=0 || elm.getInitialNodalForce(7)!=0))
			hasIniEqForce = true;
		if (gAnl.equals("Beam") && (elm.getInitialNodalForce(1)!=0 || elm.getInitialNodalForce(5)!=0 || elm.getInitialNodalForce(7)!=0 || elm.getInitialNodalForce(11)!=0))
			hasIniEqForce = true;
		if (gAnl.equals("Grid") && (elm.getInitialNodalForce(1)!=0 || elm.getInitialNodalForce(3)!=0 || elm.getInitialNodalForce(5)!=0 || elm.getInitialNodalForce(7)!=0 || elm.getInitialNodalForce(9)!=0 || elm.getInitialNodalForce(11)!=0))
			hasIniEqForce = true;
		if (gAnl.equals("PlaneFrame") && (elm.getInitialNodalForce(0)!=0 || elm.getInitialNodalForce(1)!=0 || elm.getInitialNodalForce(5)!=0 || elm.getInitialNodalForce(6)!=0 || elm.getInitialNodalForce(7)!=0 || elm.getInitialNodalForce(11)!=0))
			hasIniEqForce = true;
		if (gAnl.equals("SpaceTruss") && (elm.getInitialNodalForce(0)!=0 || elm.getInitialNodalForce(1)!=0 || elm.getInitialNodalForce(2)!=0 || elm.getInitialNodalForce(6)!=0 || elm.getInitialNodalForce(7)!=0 || elm.getInitialNodalForce(8)!=0))
			hasIniEqForce = true;
		if (gAnl.equals("SpaceFrame") && (elm.getInitialNodalForce(0)!=0 || elm.getInitialNodalForce(1)!=0 || elm.getInitialNodalForce(2)!=0 || elm.getInitialNodalForce(3)!=0 || elm.getInitialNodalForce(4)!=0 || elm.getInitialNodalForce(5)!=0 || elm.getInitialNodalForce(6)!=0 || elm.getInitialNodalForce(7)!=0 || elm.getInitialNodalForce(8)!=0 || elm.getInitialNodalForce(9)!=0 || elm.getInitialNodalForce(10)!=0 || elm.getInitialNodalForce(11)!=0))
			hasIniEqForce = true;
		
		if (hasIniEqForce) {
			fmt.applyPattern("####0.000");
			handler.startElement("iniEqForce");
			handler.element("fx1", fmt.format(elm.getInitialNodalForce(0)));
			handler.element("fy1", fmt.format(elm.getInitialNodalForce(1)));
			handler.element("fz1", fmt.format(elm.getInitialNodalForce(2)));
			handler.element("mx1", fmt.format(elm.getInitialNodalForce(3)));
			handler.element("my1", fmt.format(elm.getInitialNodalForce(4)));
			handler.element("mz1", fmt.format(elm.getInitialNodalForce(5)));
			handler.element("fx2", fmt.format(elm.getInitialNodalForce(6)));
			handler.element("fy2", fmt.format(elm.getInitialNodalForce(7)));
			handler.element("fz2", fmt.format(elm.getInitialNodalForce(8)));
			handler.element("mx2", fmt.format(elm.getInitialNodalForce(9)));
			handler.element("my2", fmt.format(elm.getInitialNodalForce(10)));
			handler.element("mz2", fmt.format(elm.getInitialNodalForce(11)));
			handler.endElement("iniEqForce");
		}
		
		// ***************** TO BE IMPLEMENTED ******************** //
		//Elastic Connections
		/*
		boolean hasElaConnection = false;
		if (gAnl.equals("PlaneTruss") && (elm.getInitialNodalForce(0)!=0 || elm.getInitialNodalForce(1)!=0))
			hasElaConnection = true;
		if (gAnl.equals("Beam") && (elm.getInitialNodalForce(1)!=0 || elm.getInitialNodalForce(5)!=0))
			hasElaConnection = true;
		if (gAnl.equals("Grid") && (elm.getInitialNodalForce(1)!=0 || elm.getInitialNodalForce(3)!=0 || elm.getInitialNodalForce(5)!=0))
			hasElaConnection = true;
		if (gAnl.equals("PlaneFrame") && (elm.getInitialNodalForce(0)!=0 || elm.getInitialNodalForce(1)!=0 || elm.getInitialNodalForce(5)!=0))
			hasElaConnection = true;
		if (gAnl.equals("SpaceTruss") && (elm.getInitialNodalForce(0)!=0 || elm.getInitialNodalForce(1)!=0 || elm.getInitialNodalForce(2)!=0))
			hasElaConnection = true;
		if (gAnl.equals("SpaceFrame") && (elm.getInitialNodalForce(0)!=0 || elm.getInitialNodalForce(1)!=0 || elm.getInitialNodalForce(2)!=0 || elm.getInitialNodalForce(3)!=0 || elm.getInitialNodalForce(4)!=0 || elm.getInitialNodalForce(5)!=0))
			hasElaConnection = true;
		
		if (hasElaConnection) {
			fmt.applyPattern("0.000E00");
			handler.startElement("elasticConnection");
			handler.element("kdx1", " ");
			handler.element("kdy1", " ");
			handler.element("kdz1", " ");
			handler.element("krx1", " ");
			handler.element("kry1", " ");
			handler.element("krz1", " ");
			handler.element("kdx2", " ");
			handler.element("kdy2", " ");
			handler.element("kdz2", " ");
			handler.element("krx2", " ");
			handler.element("kry2", " ");
			handler.element("krz2", " ");
			handler.endElement("elasticConnection");
		}
		*/
		
		//Actions at Extremities
		fmt.applyPattern("####0.000");
		handler.startElement("actionsAtExtremities");
		handler.element("fx1", fmt.format(elm.getActionAtExtremity(0)));
		handler.element("fy1", fmt.format(elm.getActionAtExtremity(1)));
		handler.element("fz1", fmt.format(elm.getActionAtExtremity(2)));
		handler.element("mx1", fmt.format(elm.getActionAtExtremity(3)));
		handler.element("my1", fmt.format(elm.getActionAtExtremity(4)));
		handler.element("mz1", fmt.format(elm.getActionAtExtremity(5)));
		handler.element("fx2", fmt.format(elm.getActionAtExtremity(6)));
		handler.element("fy2", fmt.format(elm.getActionAtExtremity(7)));
		handler.element("fz2", fmt.format(elm.getActionAtExtremity(8)));
		handler.element("mx2", fmt.format(elm.getActionAtExtremity(9)));
		handler.element("my2", fmt.format(elm.getActionAtExtremity(10)));
		handler.element("mz2", fmt.format(elm.getActionAtExtremity(11)));
		handler.endElement("actionsAtExtremities");
		
		handler.endElement("element");
		
	}
	
//********************************************************************************
}

